import pandas as pd
import matplotlib.pyplot as plt
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import plotly.express as px
from plotly.colors import n_colors
read_file = pd.read_excel('datasets\Sar_obl.xls')
read_file.to_csv('datasets\Sar_obl.csv', index = None, header=True)
data = read_file
data.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 15401 entries, 0 to 15400 Data columns (total 24 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 agrofields_regions_64_season_20190_id_633.FID 15401 non-null int64 1 agrofields_regions_64_season_20190_id_633.sub_name 15401 non-null object 2 agrofields_regions_64_season_20190_id_633.sub_kad 15401 non-null int64 3 agrofields_regions_64_season_20190_id_633.reg_cad 15401 non-null object 4 agrofields_regions_64_season_20190_id_633.reg_name 15401 non-null object 5 agrofields_regions_64_season_20190_id_633.reg_oktmo 15401 non-null int64 6 agrofields_regions_64_season_20190_id_633.cad_num 15401 non-null object 7 agrofields_regions_64_season_20190_id_633.id_sub 15401 non-null object 8 agrofields_regions_64_season_20190_id_633.area 15401 non-null float64 9 agrofields_regions_64_season_20190_id_633.date_act 15401 non-null datetime64[ns] 10 agrofields_regions_64_season_20190_id_633.tlu 15401 non-null int64 11 agrofields_regions_64_season_20190_id_633.crop_plan 15401 non-null int64 12 agrofields_regions_64_season_20190_id_633.crop_fact 15401 non-null int64 13 agrofields_regions_64_season_20190_id_633.landuser 15401 non-null object 14 agrofields_regions_64_season_20190_id_633.land_inn 15401 non-null int64 15 agrofields_regions_64_season_20190_id_633.organic 15401 non-null int64 16 agrofields_regions_64_season_20190_id_633.status_isp 15401 non-null int64 17 agrofields_regions_64_season_20190_id_633.fact_isp 15401 non-null int64 18 agrofields_regions_64_season_20190_id_633.form_own 15401 non-null int64 19 agrofields_regions_64_season_20190_id_633.rights 15401 non-null int64 20 agrofields_regions_64_season_20190_id_633.harv 15401 non-null float64 21 agrofields_regions_64_season_20190_id_633.gross_harv 15401 non-null float64 22 Справочник_культур3.csv.codes 11880 non-null float64 23 Справочник_культур3.csv.crop 11880 non-null object dtypes: datetime64[ns](1), float64(4), int64(12), object(7) memory usage: 2.8+ MB
sar_obl = data.filter(
['agrofields_regions_64_season_20190_id_633.FID','agrofields_regions_64_season_20190_id_633.reg_name',
'agrofields_regions_64_season_20190_id_633.reg_oktmo','agrofields_regions_64_season_20190_id_633.area',
'agrofields_regions_64_season_20190_id_633.landuser', 'agrofields_regions_64_season_20190_id_633.crop_fact',
'Справочник_культур3.csv.crop'], axis=1)
sar_obl = sar_obl.rename(
columns={"agrofields_regions_64_season_20190_id_633.FID": "FID", "agrofields_regions_64_season_20190_id_633.reg_name": "reg_name",
"agrofields_regions_64_season_20190_id_633.reg_oktmo": "reg_id", "agrofields_regions_64_season_20190_id_633.area": "area",
"agrofields_regions_64_season_20190_id_633.landuser": "landuser", "agrofields_regions_64_season_20190_id_633.crop_fact": "crop_code",
"Справочник_культур3.csv.crop": "crop_name"})
sar_obl['crop_name'] = sar_obl['crop_name'].fillna('нет данных')
sar_obl['area'] = round(sar_obl['area'], 2)
sar_obl = sar_obl.sort_values(by = 'FID').reset_index(drop=True)
sar_obl = sar_obl.drop('FID', axis=1)
sar_obl['reg_name'] = sar_obl['reg_name'].str.replace(' муниципальный район', '')
display(sar_obl)
sar_obl.info()
| reg_name | reg_id | area | landuser | crop_code | crop_name | |
|---|---|---|---|---|---|---|
| 0 | Перелюбский | 63634000 | 54.03 | ИП Глава КФХ Казаков В.В. | 1040106 | подсолнечник |
| 1 | Петровский | 63635000 | 2.82 | ОАО Агронова-Саратов | 1040106 | подсолнечник |
| 2 | Советский | 63644000 | 232.14 | Советский район | 1040106 | подсолнечник |
| 3 | Перелюбский | 63634000 | 180.40 | ООО" Родина " | 0 | нет данных |
| 4 | Балаковский | 63607000 | 308.06 | 1010101 | пшеница озимая | |
| ... | ... | ... | ... | ... | ... | ... |
| 15396 | Петровский | 63635000 | 12.23 | ООО Успех | 1040106 | подсолнечник |
| 15397 | Марксовский | 63626000 | 78.79 | ООО "Наше дело" | 1010101 | пшеница озимая |
| 15398 | Петровский | 63635000 | 392.35 | ИП глава КФХ Киреев П.Н. | 1010203 | овес |
| 15399 | Балаковский | 63607000 | 3.49 | 0 | нет данных | |
| 15400 | Балаковский | 63607000 | 22.96 | 0 | нет данных |
15401 rows × 6 columns
<class 'pandas.core.frame.DataFrame'> RangeIndex: 15401 entries, 0 to 15400 Data columns (total 6 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 reg_name 15401 non-null object 1 reg_id 15401 non-null int64 2 area 15401 non-null float64 3 landuser 15401 non-null object 4 crop_code 15401 non-null int64 5 crop_name 15401 non-null object dtypes: float64(1), int64(2), object(3) memory usage: 722.0+ KB
sar_obl['crop_name'].unique()
array(['подсолнечник', 'нет данных', 'пшеница озимая', 'нут',
'пар черный', 'кукуруза на силос', 'ячмень яровой', 'кукуруза',
'пшеница яровая', 'просо', 'суданская трава', 'рожь яровая',
'горох', 'кострец', 'овес', 'лен-долгунец', 'айва',
'озимый ячмень', 'рыжик', 'соя', 'сафлор', 'лен-кудряш', 'укроп',
'чечевица', 'гречиха', 'эспарцет', 'горчица', 'лук репчатый',
'житняк', 'люцерна', 'свекла сахарная', 'подсолнечник+зерносмесь',
'люпин', 'горох овощной', 'Ваниль', 'капуста кочанная ',
'люпин на корм', 'сорго', 'козлятник (галега восточная)', 'чеснок',
'перец', 'тритикале озимый', 'кориандр эфирно-масличный',
'расторопша', 'картофель', 'яблоня',
'зерносмесь (злаковые+ бобовые культуры) '], dtype=object)
Рассчитаем долю полей, не имеющих данных о культуре и владельце
print('Доля полей, не имеющих данных о культуре: ',
round(sar_obl[sar_obl['crop_name'] == 'нет данных']['crop_name'].count() / sar_obl['crop_name'].count()*100,2),'%', sep='')
Доля полей, не имеющих данных о культуре: 22.86%
print('Доля полей, не имеющих данных о владельце: ',
round(sar_obl[sar_obl['landuser'] == ' ']['landuser'].count() / sar_obl['landuser'].count()*100,2),'%', sep='')
Доля полей, не имеющих данных о владельце: 21.49%
Удалим только те поля, у которых нет данных о культуре.
sar_obl = sar_obl[sar_obl['crop_name'] != 'нет данных'].reset_index(drop=True)
sar_obl
| reg_name | reg_id | area | landuser | crop_code | crop_name | |
|---|---|---|---|---|---|---|
| 0 | Перелюбский | 63634000 | 54.03 | ИП Глава КФХ Казаков В.В. | 1040106 | подсолнечник |
| 1 | Петровский | 63635000 | 2.82 | ОАО Агронова-Саратов | 1040106 | подсолнечник |
| 2 | Советский | 63644000 | 232.14 | Советский район | 1040106 | подсолнечник |
| 3 | Балаковский | 63607000 | 308.06 | 1010101 | пшеница озимая | |
| 4 | Балаковский | 63607000 | 162.84 | 1020004 | нут | |
| ... | ... | ... | ... | ... | ... | ... |
| 11875 | Красноармейский | 63622000 | 97.57 | СПК "Карамышский" | 1040106 | подсолнечник |
| 11876 | Перелюбский | 63634000 | 111.45 | ОАО "Сельхозтехника" | 1040106 | подсолнечник |
| 11877 | Петровский | 63635000 | 12.23 | ООО Успех | 1040106 | подсолнечник |
| 11878 | Марксовский | 63626000 | 78.79 | ООО "Наше дело" | 1010101 | пшеница озимая |
| 11879 | Петровский | 63635000 | 392.35 | ИП глава КФХ Киреев П.Н. | 1010203 | овес |
11880 rows × 6 columns
print('Общее число культур, представленных в датасете:', sar_obl['crop_name'].nunique()-1)
#sar_obl['crop_name'].unique()
Общее число культур, представленных в датасете: 45
crop_area = sar_obl.groupby('crop_name').agg({'area':'sum'}).sort_values(by = 'area', ascending = False).reset_index()
#crop_area
labels = crop_area['crop_name']
values = crop_area['area']
sunflowers_colors = ['#F5DEB3', '#FFFACD', '#2F4F4F', '#9ACD32', '#F4A460', '#FFD700']
fig = go.Figure()
fig.add_trace(go.Pie(labels=labels, values=values, marker_colors=sunflowers_colors))
fig.update_traces(textposition='inside', textinfo='percent+label')
fig.update_layout(margin=dict(t=50, b=30, l=30, r=0))
fig.update_layout(showlegend=True, legend=dict(font=dict(size=10)))
fig.update_layout(title="Площадь под культуру",font=dict(size=16))
fig.show()
print('Общее число владельцев земель, представленных в датасете:', sar_obl['landuser'].nunique())
Общее число владельцев земель, представленных в датасете: 725
Владелец самого большого поля:
landuser_area = sar_obl[sar_obl['landuser'] != ' '].groupby('landuser').agg({'area':'sum'}).sort_values(by = 'area', ascending = False).reset_index().head(15)
landuser_area
| landuser | area | |
|---|---|---|
| 0 | ОАО "Сельхозтехника" | 76020.47 |
| 1 | АО АФ "Волга" | 29479.45 |
| 2 | КХ "Ягода" | 25223.81 |
| 3 | ООО "МТС Ершовская" | 23988.06 |
| 4 | АО ПЗ "Мелиоратор" | 23203.43 |
| 5 | АО "Зоринское" | 23043.88 |
| 6 | ООО "ТД и К" | 22938.89 |
| 7 | ООО "Новопокровское" | 21216.50 |
| 8 | ООО "Наше дело" | 20508.62 |
| 9 | ООО Садко | 19940.80 |
| 10 | ИП глава КФХ Жданов А.В. | 19661.54 |
| 11 | КФХ Еналиева Т.А. | 15696.62 |
| 12 | ООО Ягоднополянское | 15534.26 |
| 13 | ООО" Родина " | 14154.25 |
| 14 | ЗАО "Заря 2004" | 13742.67 |
Поля с площадью 0:
sar_obl[sar_obl['area'] == 0]
| reg_name | reg_id | area | landuser | crop_code | crop_name | |
|---|---|---|---|---|---|---|
| 942 | Краснокутский | 63623000 | 0.0 | СХПК "Карпенский - 4" | 1010209 | ячмень яровой |
| 943 | Краснокутский | 63623000 | 0.0 | СХПК "Карпенский - 4" | 1010209 | ячмень яровой |
| 4570 | Федоровский | 63648000 | 0.0 | ИП глава КФХ Собачко О А | 1010101 | пшеница озимая |
| 6791 | Федоровский | 63648000 | 0.0 | ООО "Мокроус Агро" | 1010101 | пшеница озимая |
Надо принять во внимание, что во время обработки датасета был использован метод round(), вместо например ceil(), который округляет всегда в большую сторону. Но это не отменяет того факта, что эти поля невероятно малы.
discrete = n_colors('rgb(255,215,0)', 'rgb(50,205,50)', 20, colortype = 'rgb')
fig = px.bar(landuser_area, x='landuser', y='area', title = 'Суммарная площадь всех полей каждого землевладельца (топ 15)',
text='area', height=600, color= 'landuser', color_discrete_sequence=discrete,
labels={"area": "Площадь, га","landuser": "Владелец"})
fig.update_layout(uniformtext_minsize=8, uniformtext_mode='hide', showlegend=False)
fig.update_traces(texttemplate='%{text:.2s}', textposition='outside')
fig.show()
Также можно подсчитать и визуализировать по количеству полей и по средней площади поля для каждого землевладельца
field_count = sar_obl[sar_obl['landuser'] != ' '].groupby('landuser').agg({'area':'count'}).sort_values(by = 'area', ascending = False).reset_index().head(5)
print('Количество полей у каждого землевладельца (топ 5):')
field_count
Количество полей у каждого землевладельца (топ 5):
| landuser | area | |
|---|---|---|
| 0 | ОАО "Сельхозтехника" | 290 |
| 1 | ООО "Зерновик" | 182 |
| 2 | КХ "Ягода" | 156 |
| 3 | ООО "Новопокровское" | 155 |
| 4 | АО АФ "Волга" | 151 |
print('Общее число муниципальных районов, представленных в датасете:', sar_obl['reg_name'].nunique())
Общее число муниципальных районов, представленных в датасете: 25
reg_df = sar_obl.groupby('reg_name').agg({'area':'sum'}).sort_values(by = 'area', ascending = False).reset_index()
reg_df
print('Больше всего площади под сельскохозяйственные поля в районе:', reg_df['reg_name'][0])
Больше всего площади под сельскохозяйственные поля в районе: Перелюбский
discrete = n_colors('rgb(135,206,250)', 'rgb(255,20,147)', 25, colortype = 'rgb')
fig = px.bar(reg_df, x='reg_name', y='area', title = 'Суммарная площадь всех полей каждого района Саратовской области, га',
text='area', height=600, color= 'reg_name', color_discrete_sequence=discrete,
labels={"area": "Площадь, га","reg_name": "Мунициальный район"})
fig.update_layout(uniformtext_minsize=8, uniformtext_mode='hide', showlegend=False)
fig.update_traces(texttemplate='%{text:.2s}', textposition='outside')
fig.update_xaxes(tickangle=30)
fig.show()
reg = sar_obl.groupby(['reg_name', 'crop_name']).agg({'area':'sum'}).sort_values(by = ['reg_name', 'area'], ascending = False)
#display(reg)
reg=reg.reset_index()
fig = px.sunburst(reg, path=['reg_name','crop_name'], values='area', title = 'Регионы и культуры, выращиваемые на их полях')
fig.update_layout(margin=dict(t=40, b=0, l=0, r=0))
fig.show()
Регион и самая распростаненная культура на её полях:
reg_top_crop = reg.groupby('reg_name').head(1).sort_values(by = 'reg_name').reset_index(drop=True)
reg_top_crop = reg_top_crop.loc[:, ['reg_name','crop_name']]
display(reg_top_crop)
| reg_name | crop_name | |
|---|---|---|
| 0 | Александрово-Гайский | житняк |
| 1 | Аткарский | пшеница озимая |
| 2 | Базарно-Карабулакский | подсолнечник |
| 3 | Балаковский | подсолнечник |
| 4 | Балтайский | пшеница озимая |
| 5 | Вольский | подсолнечник |
| 6 | Дергачевский | подсолнечник |
| 7 | Ершовский | пшеница озимая |
| 8 | Красноармейский | пар черный |
| 9 | Краснокутский | пшеница озимая |
| 10 | Краснопартизанский | подсолнечник |
| 11 | Марксовский | пар черный |
| 12 | Новобурасский | подсолнечник |
| 13 | Новоузенский | пшеница озимая |
| 14 | Перелюбский | подсолнечник |
| 15 | Петровский | подсолнечник |
| 16 | Питерский | пшеница озимая |
| 17 | Пугачевский | подсолнечник |
| 18 | Ровенский | подсолнечник |
| 19 | Романовский | пшеница озимая |
| 20 | Саратовский | пар черный |
| 21 | Советский | пшеница озимая |
| 22 | Татищевский | пар черный |
| 23 | Федоровский | пшеница озимая |
| 24 | Энгельсский | подсолнечник |
Количество различных культур, выращиваемых на полях каждого региона:
reg_crop_count = reg.groupby('reg_name').agg({'crop_name':'nunique'}).sort_values(by = 'crop_name', ascending = False).reset_index()
reg_crop_count
| reg_name | crop_name | |
|---|---|---|
| 0 | Балаковский | 24 |
| 1 | Петровский | 23 |
| 2 | Марксовский | 21 |
| 3 | Татищевский | 19 |
| 4 | Балтайский | 17 |
| 5 | Романовский | 17 |
| 6 | Краснопартизанский | 17 |
| 7 | Краснокутский | 16 |
| 8 | Красноармейский | 15 |
| 9 | Перелюбский | 15 |
| 10 | Советский | 14 |
| 11 | Федоровский | 12 |
| 12 | Питерский | 12 |
| 13 | Пугачевский | 7 |
| 14 | Александрово-Гайский | 6 |
| 15 | Новобурасский | 4 |
| 16 | Ершовский | 4 |
| 17 | Вольский | 3 |
| 18 | Энгельсский | 3 |
| 19 | Новоузенский | 2 |
| 20 | Ровенский | 2 |
| 21 | Дергачевский | 2 |
| 22 | Аткарский | 1 |
| 23 | Саратовский | 1 |
| 24 | Базарно-Карабулакский | 1 |